package com.panda.web.controller.system;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.panda.common.constant.Constants;
import com.panda.common.core.domain.AjaxResult;
import com.panda.common.core.domain.R;
import com.panda.common.core.domain.model.WeChatLogin;

import com.panda.framework.web.service.SysLoginService;
import com.panda.system.mapper.SysUserMapper;
import com.panda.system.mapper.SysUserRoleMapper;
import com.panda.system.service.ISysUserService;

import com.panda.web.entity.wechat.WechatGzh;
import com.panda.web.entity.wechat.WechatUser;

import com.panda.web.mapper.wechat.WechatGzhMapper;
import com.panda.web.mapper.wechat.WechatUserMapper;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/auth")
public class AuthController {
    @Autowired
    private ISysUserService userService;
    @Autowired
    private SysLoginService loginService;

    @Value("${wechat.miniapp.appid}")
    private String appid;

    @Value("${wechat.miniapp.secret}")
    private String secret;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    SysUserRoleMapper userRoleMapper;
    @Autowired
    WechatUserMapper wechatUserMapper;
    @Autowired
    WechatGzhMapper gzhMapper;


    //手机号解密
    public String decryptPhone(String encryptedData, String iv, String sessionKey) throws WxErrorException {
        if (StringUtils.isAnyBlank(sessionKey, encryptedData, iv)) {
            throw new WxErrorException("参数不可为空");
        }
        try {
            // 手动解密验证
            String rawDecrypted = manualDecrypt(sessionKey, encryptedData, iv);
            log.info("手动解密结果: {}", rawDecrypted);

            // 使用 WxJava 解密
            WxMaService wxService = new WxMaServiceImpl();
            WxMaPhoneNumberInfo phoneInfo = wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
            return phoneInfo.getPurePhoneNumber();
        } catch (WxErrorException e) {
            log.error("WxJava解密失败", e);
            throw new WxErrorException("微信服务错误: " + e.getError().getErrorMsg());
        } catch (Exception e) {
            log.error("解密过程异常", e);
            throw new WxErrorException("系统错误: " + e.getMessage());
        }
    }

    //解密验证
    public String manualDecrypt(String sessionKey, String encryptedData, String iv) throws Exception {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(sessionKey);
            byte[] ivBytes = Base64.getDecoder().decode(iv);
            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);

            // 验证密钥和IV长度
            if (keyBytes.length != 16) {
                throw new IllegalArgumentException("SessionKey解码后长度应为16字节，实际为：" + keyBytes.length);
            }
            if (ivBytes.length != 16) {
                throw new IllegalArgumentException("IV解码后长度应为16字节，实际为：" + ivBytes.length);
            }

            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");  // 修改为 PKCS5Padding
            cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivBytes));

            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
            // 去除填充
            int padSize = decryptedBytes[decryptedBytes.length - 1];
            byte[] data = Arrays.copyOfRange(decryptedBytes, 0, decryptedBytes.length - padSize);
            return new String(data, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("手动解密失败 - sessionKey: {}, iv: {}", sessionKey, iv, e);
            throw e;
        }
    }

    //完整修复后的解密方法
    public JSONObject decryptUserInfo(String encryptedData, String iv, String sessionKey) {
        try {
            Base64.Decoder decoder = Base64.getDecoder();

            byte[] data = decoder.decode(encryptedData);
            byte[] key = decoder.decode(sessionKey);
            byte[] ivData = decoder.decode(iv);

            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivSpec = new IvParameterSpec(ivData);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);

            byte[] decrypted = cipher.doFinal(data);
            return JSON.parseObject(new String(decrypted, StandardCharsets.UTF_8));
        } catch (Exception e) {
            throw new RuntimeException("解密用户信息失败: " + e.getMessage(), e);
        }
    }

    // 小程序登录
    @PostMapping("/miniapp-login")
    @Transactional
    public synchronized AjaxResult miniAppLogin(@RequestBody Map<String, String> params) throws WxErrorException {

        AjaxResult ajax = AjaxResult.success();
        String code = params.get("code");
        String encryptedData = params.get("encryptedData");
        String iv = params.get("iv");
        // 调用微信接口换取 openid

// 获取 openid 和 session_key
        String url = String.format(
                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                appid, secret, code
        );
        ResponseEntity<String> response = new RestTemplate().getForEntity(url, String.class);
        JSONObject result = JSON.parseObject(response.getBody());

        if (result.containsKey("errcode")) {
            return AjaxResult.error("微信登录失败: " + result.getString("errmsg"));
        }

        String openid = result.getString("openid");
        String sessionKey = result.getString("session_key");
        String unionId = result.getString("unionid");
        System.out.println(unionId);
        String phone = decryptPhone(encryptedData, iv, sessionKey);  // 解密手机号


        // 查询或创建用户
//        WechatUser wechatUser = wechatUserMapper.findByOpenId(openid);
        WechatUser wechatUser = wechatUserMapper.findByPhoneNumber(phone);
        if (wechatUser != null) {  //更新账号
            if (Objects.equals(wechatUser.getStatus(), "0")) {
//                    // 生成token
//                  String token = weChatLogin(wechatUser.getOpenid());
                wechatUser.setPhone(phone);
                if (unionId != null) {
                    WechatGzh wechatGzh = gzhMapper.findByUnionid(unionId);
                    if (wechatGzh != null) {
                        wechatUser.setOfficialOpenid(wechatGzh.getOpenid());
                        wechatUser.setFollowStatus("1");
                    }
                    wechatUser.setUnionid(unionId);
                }
                wechatUser.setAccessToken(sessionKey);
                wechatUser.setMiniOpenid(openid);
                wechatUser.setUpdateDate(new Date());
                wechatUserMapper.updateById(wechatUser);
                String token = loginService.login(openid, "a12345678", null, null, null);
                ajax.put("openid", wechatUser.getOpenid());
                ajax.put(Constants.TOKEN, token);
                return ajax;
            } else {
                throw new RuntimeException("账号异常");//此用户已拉黑
            }

        } else {//正常账号
            WechatUser wechatUserStatus= wechatUserMapper.findByOpenId(openid);
            if (wechatUserStatus!=null){
                throw new RuntimeException("此微信已存在账号，原登录手机号为："+wechatUserStatus.getPhoneNumber());
            }

            wechatUser = new WechatUser();
            wechatUser.setPhoneNumber(phone);
            wechatUser.setAccessToken(sessionKey);
            wechatUser.setOpenid(openid);
            if (unionId != null) {
                WechatGzh wechatGzh = gzhMapper.findByUnionid(unionId);
                if (wechatGzh != null) {
                    wechatUser.setOfficialOpenid(wechatGzh.getOpenid());
                    wechatUser.setFollowStatus("1");
                }
                wechatUser.setUnionid(unionId);
            }
            wechatUser.setMiniOpenid(openid);
            wechatUser.setNickname("小程序用户");
            wechatUser.setHeadimgurl("https://houtaiguanli.yanbeibao2021.com/file/document/moren.png");
            wechatUser.setCreateDate(new Date());
            wechatUser.setUpdateDate(new Date());
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();
            // 定义格式化器
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            // 格式化当前时间
            String formattedDate = now.format(formatter);
            wechatUser.setCreationTime(formattedDate);
            wechatUserMapper.insert(wechatUser);
            // 生成token
            String token = loginService.login(openid, "a12345678", null, null, null);
            log.info("openid:{}, token:{}", openid, token);
            ajax.put("openid", openid);
            ajax.put(Constants.TOKEN, token);
            return ajax;
        }
    }


//    // 小程序登录
//    @PostMapping("/miniapp-login")
//    @Transactional
//    public synchronized AjaxResult miniAppLogin(@RequestBody Map<String, String> params) throws WxErrorException {
//        AjaxResult ajax = AjaxResult.success();
//        String code = params.get("code");
//        String encryptedData = params.get("encryptedData");
//        String iv = params.get("iv");
//        // 调用微信接口换取 openid
//
//// 获取 openid 和 session_key
//        String url = String.format(
//                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
//                appid, secret, code
//        );
//        ResponseEntity<String> response = new RestTemplate().getForEntity(url, String.class);
//        JSONObject result = JSON.parseObject(response.getBody());
//
//        if (result.containsKey("errcode")) {
//            return AjaxResult.error("微信登录失败: " + result.getString("errmsg"));
//        }
//
//        String openid = result.getString("openid");
//        String sessionKey = result.getString("session_key");
//        String phone = decryptPhone(encryptedData, iv, sessionKey);  // 解密手机号
//        JSONObject userInfo = decryptUserInfo(encryptedData, iv, sessionKey);
//        // 获取用户信息
//        String unionId = userInfo.getString("unionid");
//        System.out.println(unionId);
//
//        // 查询或创建用户
//        WechatUser wechatUser = wechatUserMapper.findByOpenId(openid);
//        if (wechatUser != null) {  //更新账号
//            if (Objects.equals(wechatUser.getStatus(), "0")) {
//                String token = loginService.login(openid, "a12345678", null, null, null);
////                    // 生成token
////                  String token = weChatLogin(wechatUser.getOpenid());
//                wechatUser.setPhone(phone);
//                wechatUser.setAccessToken(sessionKey);
//                wechatUser.setUpdateDate(new Date());
//                wechatUserMapper.updateById(wechatUser);
//                ajax.put("openid",openid);
//                ajax.put(Constants.TOKEN, token);
//                return ajax;
//            } else {
//                throw new RuntimeException("账号异常");//此用户已拉黑
//            }
//
//        } else {//正常账号
//
//            wechatUser = new WechatUser();
//            wechatUser.setPhone(phone);
//            wechatUser.setAccessToken(sessionKey);
//            wechatUser.setOpenid(openid);
//            wechatUser.setNickname("小程序用户");
//            wechatUser.setHeadimgurl("http://mzyy.changbeiyiyao.com/file/document/moren.png");
//            wechatUser.setCreateDate(new Date());
//            wechatUser.setUpdateDate(new Date());
//            // 获取当前时间
//            LocalDateTime now = LocalDateTime.now();
//            // 定义格式化器
//            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//            // 格式化当前时间
//            String formattedDate = now.format(formatter);
//            wechatUser.setCreationTime(formattedDate);
//            wechatUserMapper.insert(wechatUser);
//            // 生成token
//            String token = loginService.login(openid, "a12345678", null, null, null);
//            ajax.put("openid",openid);
//            ajax.put(Constants.TOKEN, token);
//            return ajax;
//        }
//    }
//    //公众号登录
//    /**
//     * 根据code 获取openId
//     */
//    @GetMapping("/gzh/code")
//    public R login(@RequestParam("code") String code) throws Exception {
//        Map<String,String> vo = userService.getOpenId(code);    // 生成令牌
//        return R.ok(vo, "ok");
//
//    }


    @GetMapping("/share/config")
    public R getShareConfig(@RequestParam String url) {
        String appId = "wxa53db1b195aafc70";
        String appSecret = "30ccdf15b16fca71930793ceb6766e6f";
        String accessToken = getAccessToken(appId, appSecret);//需要公众号添加IP白名单 如：39.105.32.156，119.162.226.251

        String jsapiTicket = getJsapiTicket(accessToken);

        long timestamp = System.currentTimeMillis() / 1000;
        String nonceStr = UUID.randomUUID().toString();
        String signature = generateSignature(jsapiTicket, nonceStr, timestamp, url);

        Map<String, String> config = new HashMap<>();
        config.put("appId", appId);
        config.put("timestamp", String.valueOf(timestamp));
        config.put("nonceStr", nonceStr);
        config.put("signature", signature);

        return R.ok(config, 200, "ok");
    }

    public String getAccessToken(String appId, String appSecret) {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
        String result = get(url); // 使用 HTTP 工具类发送请求
        JSONObject jsonObject = JSONObject.parseObject(result);

        // 检查返回的JSON是否含有access_token
        if (jsonObject.containsKey("access_token")) {
            return jsonObject.getString("access_token");
        } else {
            // 错误处理：返回API错误信息
            String errorMsg = jsonObject.getString("errmsg");
            System.out.println("Error fetching access token: " + errorMsg);
            return null;
        }
    }

    public String getJsapiTicket(String accessToken) {
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
        String result = get(url);
        JSONObject jsonObject = JSONObject.parseObject(result);
        return jsonObject.getString("ticket");
    }

    public String generateSignature(String jsapiTicket, String nonceStr, long timestamp, String url) {
        String string1 = "jsapi_ticket=" + jsapiTicket +
                "&noncestr=" + nonceStr +
                "&timestamp=" + timestamp +
                "&url=" + url;
        return org.apache.commons.codec.digest.DigestUtils.sha1Hex(string1); // 使用 Apache Commons Codec 的 SHA1 工具类
    }

    /**
     * 获取个人信息
     *
     * @param
     * @return
     */
    @GetMapping("/getinfo")
    public R getInfo(WeChatLogin weChatLogin) {
        WeChatLogin userInfoVO = new WeChatLogin();
        String openId = weChatLogin.getOpenId();
        WechatUser wechatUser = wechatUserMapper.findByOpenId(openId);
        BeanUtils.copyProperties(wechatUser, userInfoVO);
        return R.ok(userInfoVO);
    }

    /**
     * HTTP GET 请求方法
     */
    public String httpGet(String requestUrl) throws Exception {
        URL url = new URL(requestUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        return response.toString();
    }

//    // 随机密码生成工具方法
//    private String generateRandomPassword(int length) {
//        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//        SecureRandom random = new SecureRandom();
//        StringBuilder sb = new StringBuilder();
//        for (int i = 0; i < length; i++) {
//            sb.append(chars.charAt(random.nextInt(chars.length())));
//        }
//        return sb.toString();
//    }

    public static String get(String urlString) {
        StringBuilder result = new StringBuilder();
        try {
            // 创建URL对象
            URL url = new URL(urlString);
            // 打开连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET"); // 设置请求方式为GET
            connection.setConnectTimeout(10000);  // 设置连接超时时间为10秒
            connection.setReadTimeout(10000);     // 设置读取超时时间为10秒

            // 获取响应码
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {  // 200表示请求成功
                BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    result.append(inputLine);
                }
                in.close();
            } else {
                System.out.println("GET request failed: " + responseCode);
                // 获取错误流并打印出错信息
                BufferedReader errorReader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                String errorLine;
                StringBuilder errorMessage = new StringBuilder();
                while ((errorLine = errorReader.readLine()) != null) {
                    errorMessage.append(errorLine);
                }
                errorReader.close();
                System.out.println("Error response: " + errorMessage.toString());
            }
        } catch (MalformedURLException e) {
            System.out.println("Malformed URL: " + urlString);
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("IO Exception occurred while accessing the URL: " + urlString);
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("An unexpected error occurred");
            e.printStackTrace();
        }
        return result.toString();
    }


}